#include "stdafx.h"

#include <stdlib.h>

extern "C" LONG core200_RegCreateKeyExW( 
	HKEY hKey, 
	LPCWSTR lpSubKey, 
	DWORD Reserved, 
	LPWSTR lpClass, 
	DWORD dwOptions, 
	REGSAM samDesired, 
	LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
	PHKEY phkResult, 
	LPDWORD lpdwDisposition )
{
	OutputDebugString(_T("RegCreateKeyExW: "));
	OutputDebugString(lpSubKey);

	// prevent error 87
	DWORD dw;
	if (NULL == lpdwDisposition)
		lpdwDisposition = &dw;

	LONG res = RegCreateKeyExW( 
		hKey, 
		lpSubKey, 
		0,//Reserved, 
		NULL, //lpClass, 
		dwOptions, 
		samDesired, 
		NULL, //lpSecurityAttributes, 
		phkResult, 
		lpdwDisposition 
		);

#ifdef DEBUG
	TCHAR buf[300];
	swprintf( buf, _T(" hKey=0x%x opt:0x%x sam:0x%x, dis:0x%x ret:0x%x, res=%d\n"), hKey, dwOptions, samDesired, lpdwDisposition, *phkResult, res );
	OutputDebugString(buf);
#endif

	return res;
}

// converts string to wide string and returns pointer to it. returns NULL in case of erroror if lpszStr is NULL.
// the returned pointer should be released with "free".
LPWSTR str2Wstr( LPCSTR lpszStr, size_t * lpCount = NULL)
{
	if (NULL == lpszStr) return NULL;

	size_t nLen = strlen( lpszStr );
	
	if (NULL != lpCount)
		nLen = __min(nLen, *lpCount );

	nLen++;
	
	LPWSTR pBuf = (LPWSTR) malloc( nLen*2 );
	if (NULL != pBuf)
	{
		if ( -1 == mbstowcs( pBuf, lpszStr, nLen ) )
		{
			free( pBuf );
			pBuf = NULL;
		}
	}

	return pBuf;
}

extern "C" FARPROC core200_GetProcAddressA( HMODULE hModule, LPCSTR lpProcName) 
{ 
	OutputDebugString(_T("GetProcAddressA: ")); 

	if (0 != HIWORD(lpProcName) )
	{
		FARPROC ret = NULL;

		LPWSTR lpWProcName = str2Wstr( lpProcName );
		if (NULL != lpWProcName)
		{
			OutputDebugString( lpWProcName );
			OutputDebugString(_T("\n"));

			ret = GetProcAddressW( hModule, lpWProcName );
			free( lpWProcName );
		}

		return ret;
	}
	else
	{
		OutputDebugString(_T("\n"));
		return GetProcAddressW( hModule, (LPCWSTR) lpProcName );
	}
}

extern "C" HMODULE core200_LoadLibraryExW(
	LPCWSTR lpLibFileName, 
	HANDLE hFile, 
	DWORD dwFlags )
{
	OutputDebugString(_T("LoadLibraryExW: "));
	OutputDebugString(lpLibFileName);
	OutputDebugString(_T("\n"));

	return LoadLibraryW( lpLibFileName );
}

extern "C" BOOL core200_CryptImportKey( 
	HCRYPTPROV hProv,
	BYTE *pbData, 
	DWORD dwDataLen, 
	HCRYPTKEY hPubKey,
	DWORD dwFlags, 
	HCRYPTKEY *phKey)
{
	OutputDebugString(_T("CryptImportKey\n"));
	return true;
}


extern "C" BOOL core200_CryptCreateHash( 
	HCRYPTPROV hProv,
	ALG_ID Algid, 
	HCRYPTKEY hKey, 
	DWORD dwFlags, 
	HCRYPTHASH *phHash)
{
	OutputDebugString(_T("CryptCreateHash\n"));
	return true;
}

extern "C" BOOL core200_CryptHashData( 
	HCRYPTHASH hHash, 
	BYTE *pbData,
	DWORD dwDataLen, 
	DWORD dwFlags)
{
	OutputDebugString(_T("CryptHashData\n"));
	return true;
}

extern "C" BOOL WINAPI core200_CryptVerifySignatureW(
  HCRYPTHASH hHash,
  BYTE* pbSignature,
  DWORD dwSigLen,
  HCRYPTKEY hPubKey,
  LPCWSTR sDescription,
  DWORD dwFlags
)
{
	OutputDebugString(_T("CryptVerifySignatureW: "));
	OutputDebugString(sDescription);
	OutputDebugString(_T("\n"));
	return true;
}

extern "C" BOOLEAN core200_CryptAcquireContextW(
	HCRYPTPROV *phProv,
	LPCWSTR pszContainer, 
	LPCWSTR pszProvider, 
	DWORD dwProvType, 
	DWORD dwFlags)
{
	OutputDebugString(_T("CryptAcquireContextW: "));

	OutputDebugString(pszContainer);
	OutputDebugString(_T(" and "));
	OutputDebugString(pszProvider);
	OutputDebugString(_T("\n"));

	return true;
}

extern "C" BOOL core200_CryptReleaseContext( 
	HCRYPTPROV hProv,
	DWORD dwFlags)
{
	OutputDebugString(_T("CryptReleaseContext\n"));
	return true;
}

#if _WIN32_WCE==200
extern "C" int core200_toupper( int c );
#endif

extern "C" int core200__strnicmp( const char *string1, const char *string2, size_t count )
{

#ifdef DEBUG
	OutputDebugString(_T("_strnicmp: "));

//	LPWSTR wstr1 = str2Wstr( string1, &count );
//	LPWSTR wstr2 = str2Wstr( string2, &count );

//	OutputDebugString( wstr1 );
//	OutputDebugString( _T(" = ") );
//	OutputDebugString( wstr2 );
	OutputDebugString( _T("\n") );

//	if (NULL != wstr1) free(wstr1);
//	if (NULL != wstr2) free(wstr2);
#endif

#if _WIN32_WCE==200
	#define TOUPPER core200_toupper
#else
	#define TOUPPER toupper
#endif

	int c = 0;
	while ((c == 0) && (count > 0)) 
	{
		c = TOUPPER (*string1++) - TOUPPER(*string2++);
		--count;
	}

	return c;
/*

	LPWSTR pString1W = str2Wstr( string1, &count );
	LPWSTR pString2W = str2Wstr( string2, &count );

	OutputDebugString(pString1W); 
	OutputDebugString(_T(" =? ")); 
	OutputDebugString(pString2W); 
	OutputDebugString(_T("\n")); 

	int ret = _wcsnicmp( pString1W, pString2W, count );

	if (NULL != pString1W) free(pString1W);
	if (NULL != pString2W) free(pString2W);

	return ret;
*/
}

#define core200_OEM_CERTIFY_TRUST 2
extern "C" DWORD core200_CeGetCallerTrust()
{
	OutputDebugString(_T("CeGetCallerTrust\n")); 

	return core200_OEM_CERTIFY_TRUST;
}

#define core200_CSIDL_WINDOWS 0x24
extern "C" BOOL core200_SHGetSpecialFolderPath(
	HWND hwndOwner,
	LPTSTR lpszPath,
	int nFolder,
	BOOL fCreate )
{
#ifdef DEBUG
	OutputDebugString(_T("SHGetSpecialFolderPath: ")); 

	TCHAR buf[100];
	swprintf( buf, _T(" nFolder=0x%x "), nFolder );
	OutputDebugString(buf);
#endif

	if ( core200_CSIDL_WINDOWS == nFolder )
	{
		wcscpy( lpszPath, _T("\\Windows") );

		OutputDebugString(_T(" lpszPath: "));
		OutputDebugString(lpszPath);
		OutputDebugString(_T("\n"));

		return true;
	}

	lpszPath = NULL;
	SetLastError( ERROR_INVALID_PARAMETER );
	return false;
}

LPWSTR g_lpszCommandLine = NULL;

extern "C" LPWSTR core200_GetCommandLineW()
{
	OutputDebugString(_T("GetCommandLineW: "));
	
	if (NULL != g_lpszCommandLine)
		return g_lpszCommandLine;

	HKEY hKey;
	if ( ERROR_SUCCESS == RegOpenKeyEx( 
		HKEY_LOCAL_MACHINE
		, L"SOFTWARE\\Microsoft\\.NETCompactFramework"
		, 0
		, KEY_QUERY_VALUE | KEY_SET_VALUE
		, &hKey ) )
	{
		DWORD dwSize = 0;
		LONG lRes = RegQueryValueEx( hKey, _T("CommandLine"), 0, 0, NULL, &dwSize );

		if (ERROR_SUCCESS == lRes && 0<dwSize)
		{
			LPWSTR lpszCommandLine = (LPWSTR) malloc(dwSize );

			lRes = RegQueryValueEx( hKey, _T("CommandLine"), 0, 0, (LPBYTE) lpszCommandLine, &dwSize );

			RegDeleteValue( hKey, _T("CommandLine") ); 

			RegCloseKey( hKey );

			if ( ERROR_SUCCESS == lRes )
			{
				OutputDebugString( lpszCommandLine );
				OutputDebugString( _T("\n") );

				g_lpszCommandLine = lpszCommandLine;
				return lpszCommandLine;
			}
		}
	}

	OutputDebugString(_T("(not supported) !!!\n"));
	SetLastError( ERROR_NOT_SUPPORTED );
	return L"";
}

extern "C" int core200__isctype( int c, int desc )
{
	return iswctype( c, desc );
}

#if NET1SP3
int nGetVersionExW = 0;
extern "C" BOOL core200_GetVersionExW( LPOSVERSIONINFO lpVersionInfo )
{ 
	nGetVersionExW++;

#ifdef DEBUG
	OutputDebugString(_T("GetVersionExW: "));

	OSVERSIONINFO versionInfo;
	versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

	TCHAR buf[100];
	swprintf( buf, _T(" lpVersionInfo=0x%x"), lpVersionInfo );
	OutputDebugString(buf);

	swprintf( buf, _T(" size=%d, standard size=%d\n"), lpVersionInfo->dwOSVersionInfoSize, versionInfo.dwOSVersionInfoSize);
	OutputDebugString(buf);
#endif

	if ( GetVersionEx( lpVersionInfo ) )
	{
#if DEBUG
		swprintf( buf, _T(" dwMajorVersion=0x%x res = OK\n"), lpVersionInfo->dwMajorVersion );
		OutputDebugString(buf);
#endif
		// return version 3 only the first two times. 
		// PALHost_Register calls GetVersionExW twice.
		if (nGetVersionExW <= 2)
			lpVersionInfo->dwMajorVersion = 3;

		return true;
	}
	else
	{
		OutputDebugString(_T(" res = ERROR\n"));
		return false;
	}
}
#endif // NET1SP3
